import 'dart:math';

import 'package:flutter/material.dart';

class RepaintBoundaryTest extends StatefulWidget {
  @override
  _RepaintBoundaryTestState createState() => _RepaintBoundaryTestState();
}

class _RepaintBoundaryTestState extends State<RepaintBoundaryTest>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  GlobalKey _paintKey = GlobalKey();
  Offset _offset;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this);
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('layer优化'),
      ),
      body: Stack(
        fit: StackFit.expand,
        children: <Widget>[
          CustomPaint(
            painter: ExpensivePainter(),
            isComplex: true,
            willChange: false,
          ),
          Listener(
            onPointerDown: _updateOffset,
            onPointerMove: _updateOffset,
            child: RepaintBoundary(//这里翻了天 打开卡到死
              child: CustomPaint(
                key: _paintKey,
                painter: MyCustomPainter(_offset),
                child: ConstrainedBox(
                  constraints: BoxConstraints.expand(),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }

  _updateOffset(PointerEvent event) {
    RenderBox referenceBox = _paintKey.currentContext.findRenderObject();
    Offset offset = referenceBox.globalToLocal(event.position);
    setState(() {
      _offset = offset;
    });
  }
}

class ExpensivePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    print("Doing expensive paint job");
    Random rand = Random(12345);
    List<Color> colors = [
      Colors.red,
      Colors.blue,
      Colors.yellow,
      Colors.green,
      Colors.white,
    ];
    for (int i = 0; i < 5000; i++) {
      canvas.drawCircle(
          Offset(
              rand.nextDouble() * size.width, rand.nextDouble() * size.height),
          10 + rand.nextDouble() * 20,
          Paint()
            ..color = colors[rand.nextInt(colors.length)].withOpacity(0.2));
    }
  }

  @override
  bool shouldRepaint(ExpensivePainter other) => false;
}

class MyCustomPainter extends CustomPainter {
  final Offset _offset;

  MyCustomPainter(this._offset);

  @override
  void paint(Canvas canvas, Size size) {
    if (_offset == null) return;
    canvas.drawCircle(_offset, 10.0, Paint()..color = Colors.black);
  }

  @override
  bool shouldRepaint(MyCustomPainter other) => other._offset != _offset;
}
